#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===============================================================================
# Copyright 2011 zod.yslin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 
# Author: zod.yslin
# Email: 
# File Name: newstyle.py
# Description: 
#   New-style classes were introduced in Python 2.2 to unify classes and types. 
#   A new-style class neither more nor less than a user-defined type. 
#   If x is an instance of a new-style class, then type(x) is the same as x.__class__.
#   
#   For compatibility reasons, classes are still old-style by default. 
#   New-style classes are created by specifying another new-style class 
#   (i.e. a type) as a parent class, or the "top-level type" object if no other 
#   parent is needed. The behaviour of new-style classes differs from that of 
#   old-style classes in a number of important details in addition to what type returns.
#
#   1. super并不是一个函数，是一个类名，形如super(B, self)事实上调用了super类的初始化函数，
#      产生了一个super对象；
#   2. super类的初始化函数并没有做什么特殊的操作，只是简单记录了类类型和具体实例；
#   3. super(B, self).func的调用并不是用于调用当前类的父类的func函数；
#   4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用，而且保证每个父类函数
#      只调用一次（如果每个类都使用super）；
#   5. 混用super类和非绑定的函数是一个危险行为，这可能导致应该调用的父类函数没有调用或者一
#      个父类函数被调用多次。
#
# Edit History: 
#   2011-08-12    File created.
#===============================================================================
class newstyle(object):
    def __init(self):
        print "newstyle"

c = newstyle()        
print type(c)
print c.__class__


class A(object):    # A must be new-style class
    def __init__(self):
        print "enter A"
        print "leave A"
class B(A):     
    def __init__(self):
        print "enter B"
        super(B, self).__init__()
        print "leave B"

#b = B()

#   object
#      |  \
#      |    A
#      |   / |
#      B  C  D
#      \ /   |
#       E    |
#        \   |
#           F
class A(object):
    indent = ""
    def __init__(self):
        print A.indent + "A{"
        A.indent += "  "
        super(A, self).__init__()  # new
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "A}"
class B(object):
    def __init__(self):
        print A.indent + "B{"
        A.indent += "  "
        super(B, self).__init__()  # new
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "B}"
class C(A):
    def __init__(self):
        print A.indent + "C{"
        A.indent += "  "
        super(C, self).__init__()
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "C}"
class D(A):
    def __init__(self):
        print A.indent + "D{"
        A.indent += "  "
        super(D, self).__init__()
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "D}"
class E(B, C):
    def __init__(self):
        print A.indent + "E{"
        A.indent += "  "
        super(E, self).__init__()  # change
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "E}"
class F(E, D):
    def __init__(self):
        print A.indent + "F{"
        A.indent += "  "
        super(F, self).__init__()  # change
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "F}"

# F的初始化不仅完成了所有的父类的调用，而且保证了每一个父类的初始化函数只调用一次
f = F()

#   object
#      |  \
#      |    A
#      |   / |
#      B  C  D
#      \ /   |
#       E    |
#        \   |
#           F
# 我们再重新看上面的类体系图，如果把每一个类看作图的一个节点，
# 每一个从子类到父类的直接继承关系看作一条有向边，那么该体系图将变为一个有向图。
# 不難发现mro的顺序正好是该有向图的一个拓扑排序序列。
# 从而，我们得到了另一个结果——Python是如何去处理多继承。支持多继承的传统的面向对象程序语言
# （如C++）是通过虚拟继承的方式去实现多继承中父类的构造函数被多次调用的问题，
# 而Python则通过mro的方式去处理
print F.__mro__
print f.__class__.mro()
